<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 导入 ol 依赖（openlayer） -->
    <link href="https://cdn.bootcdn.net/ajax/libs/ol3/4.6.5/ol.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/ol3/4.6.5/ol.js"></script>
    <style>
      *{margin:0;padding:0}
      #map{
        width:100vw;
        height: 100vh;
      }
      .ol-zoomslider { /* 调整视图跳转控件的默认样式 */
        top: 7.5em;
        border: 1px solid rgba(0, 60, 136, .5);
        padding: 0;
      }
      #resetBtn {
        position: absolute;
        top: .5em;
        right: 3.5em;
      }
    </style>
  </head>

  <body>
    <div id="map"></div>
    <button id="resetBtn">复位地图</button>
    <script>
      /* 
      * Map（地图） 由多个 Layer（图层） 组成    // PS: 还有视图、控件
      * 一个 Layer（图层） 对应一个 Source（矢量数据源）
      * 一个 Source（矢量数据源） 由很多 Feature（要素） 组成
      * Feature（要素） 由 Geometry（形状） 和 Style（样式） 组成
      */

      // 1. 初始化地图 

      // 初始化一个高德图层
      const gaode = new ol.layer.Tile({
        title: "高德地图",
        source: new ol.source.XYZ({
          // 更多地图瓦片源地址见：https://blog.csdn.net/AllBluefm/article/details/134803270
          url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}',
          wrapX: false
        })
      })
      // 初始化 openlayer 地图
      const map = new ol.Map({
        // 挂载到id为map的DOM元素上
        target: "map",
        // 设置图层
        layers: [ gaode ],
        // 设置视图
        view:new ol.View({
          center:[114.30,30.50],
          // 设置地图放大级别
          zoom:10,
          projection:'EPSG:4326'
        })
      })

      // 2. 设置地图控件

      // 视图跳转控件
      const ZoomToExtent = new ol.control.ZoomToExtent({
        extent: [110, 30, 160, 30],
      })
      map.addControl(ZoomToExtent)
      // 放大缩小控件
      const zoomslider = new ol.control.ZoomSlider();
      map.addControl(zoomslider)
      //全屏控件
      const fullScreen = new ol.control.FullScreen();
      map.addControl(fullScreen)


      // 3. 绘制一个点要素
      
      // 构建要素：通过样式信息和几何信息构建点要素
      const point = new ol.Feature({
        geometry: new ol.geom.Point([114.30, 30.50]) // 经纬度信息
      })
      let style = new ol.style.Style({
        // 设置点要素的样式
        image: new ol.style.Circle({
          radius: 10, // 半径
          fill: new ol.style.Fill({
            color: "#ff2d51"
          }),
          stroke: new ol.style.Stroke({
            color: "#333",
            width: 2
          })
        })
      })
      point.setStyle(style);
      // 将要素添加到矢量数据源
      const source = new ol.source.Vector({
        features: [point]
      })
      // 将矢量数据源添加到矢量图层
      const layer = new ol.layer.Vector({
        source
      })
      // 将矢量图层添加到地图容器
      map.addLayer(layer)


      // 4. geojson 设置一个点、线、面要素（点要素与3效果一致，geojson其实就是一个数组定义多个 Feature）
      // readGeoJSON('data')

      // 5. 加载本地 geojson 数据
      // readGeoJSON('local')

      // 6. 加载网络 geojson 数据
      // readGeoJSON('network')


      // 7. 点击在地图上设置点
      map.on("click", (evt) => {
        var position = evt.coordinate;
        var point = new ol.Feature({
              geometry: new ol.geom.Point(position)
        })
        source.addFeature(point)
      })

      // 8. 点击什么地方飞行到什么地方(漫游)
      map.on("click", (evt) => {
        var position = evt.coordinate;
        map.getView().animate({
          center: position,
          // zoom: 10,
          // duration: 2000,
        })
      })

      // 9. 复位地图
      document.getElementById('resetBtn').addEventListener('click', function() {
        map.getView().animate({
          center: [114.30, 30.50]
        })
      })

      function readGeoJSON(type) {
        let source
        switch (type) {
          // 直接使用 geojson 数据
          case 'data':
            source = new ol.source.Vector({
              features: new ol.format.GeoJSON().readFeatures({
                type: "FeatureCollection",
                features: [
                  // 点要素
                  {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: [114.30, 30.50]
                    }
                  },
                  // 线要素
                  {
                    type: "Feature",
                    geometry: {
                      type: "LineString",
                      coordinates: [[114.30, 30.50], [115, 31]]
                    }
                  },
                  // 区要素
                  {
                    type: "Feature",
                    geometry: {
                      type: "Polygon",
                      coordinates: [[[114.30, 30.50], [115, 30.50], [115, 30]]]
                    }
                  }
                ]
              })
            })
            break
          // 加载本地 geojson 数据（必须以服务的形式打开）
          case 'local':
            source = new ol.source.Vector({
              url: './data/map.geojson',
              format: new ol.format.GeoJSON()
            })
            break
          // 加载网络 geojson 数据
          case 'network':
            source = new ol.source.Vector({
              url: 'https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=420100',
              format: new ol.format.GeoJSON()
            })
            break
        }
        // 设置矢量图层放置矢量数据源
        var layer = new ol.layer.Vector({
          source
        })
        //设置样式
        const style = new ol.style.Style({
          //边线颜色
          stroke: new ol.style.Stroke({
            color: '#ff2d51',
            width: 2
          }),
          //设置填充色
          fill: new ol.style.Fill({
            color: "rgba(50, 50, 50, 0.3)"
          }),
          // 设置点要素的样式
          image: new ol.style.Circle({
            radius: 10, // 半径
            fill: new ol.style.Fill({
              color: "#ff2d51"
            }),
            stroke: new ol.style.Stroke({
              color: "#333",
              width: 2
            })
          })
        })
        layer.setStyle(style)
        // 将矢量图层添加到地图容器
        map.addLayer(layer)
      }
    </script>
  </body>
</html>